﻿using Game.CheseBoard.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;
using QFramework;
using Game.Util;
using UnityEngine.EventSystems;
using Game.UI;
using Game.Assets.Scripts.Model;
using Game.Command;

namespace Game.CheseBoard
{
    /// <summary>
    /// 拖拽棋子的目标
    /// </summary>
    public interface IPieceDrag
    {
        public bool OnEndDrag(Cell dragCell, out int index);
    }
    /// <summary>
    /// 拆分器
    /// </summary>
    public interface ISplitter
    {
        public bool CanSplitter(int maxLv);
        public void OnSplitter();
    }
    /// <summary>
    /// 升级
    /// </summary>
    public interface IUpgrade
    {
        public bool CanUpgrade();
        public void Upgrade();
    }

    public class Cell : MonoBehaviour, IController, IPieceDrag, ISplitter, IUpgrade, ICanvasRaycastFilter
    {
        public IArchitecture GetArchitecture()
        {
            return APP.Interface;
        }
        protected static (int x, int y) CalculatePos(int i)
        {
            return (i / ChessModel.COL, i % ChessModel.COL);
        }

        public CellType cellType;

        public CellState cellState;

        public Transform cellRoot;
        public Image mainImage;

        protected BaseCell data;
        public BaseCell Data => data;
        public int Index => transform.parent.GetSiblingIndex();
        protected bool beDestroyed;
        protected virtual void Awake()
        {
            gameObject.OnBeginDragEvent(OnBeginDragEvent);
            gameObject.OnDragEvent(OnDragEvent);
            gameObject.OnEndDragEvent(OnEndDragEvent);
            gameObject.OnPointerClickEvent(OnPointerClickEvent);

            this.SendCommand(new RegisterCellCommand(this));

            TypeEventSystem.Global.Register<BeginDragEvent>(OnBeginDragEvent).UnRegisterWhenGameObjectDestroyed(gameObject);
            TypeEventSystem.Global.Register<EndDragEvent>(OnEndDragEvent).UnRegisterWhenGameObjectDestroyed(gameObject);
        }
        private void OnDestroy()
        {
            this.SendCommand(new UnregisterCellCommand(this));
        }

        public void Init()
        {
            switch (cellType)
            {
                case CellType.Empty:
                    break;
                case CellType.Piece:
                    data = new PieceCell();
                    break;
                case CellType.Producer:
                    data = new ProducerCell();
                    break;
                case CellType.ExtraItem:
                    data = new ExtraItemCell();
                    break;
            }

            data.RandomStaticData();
        }

        /// <summary>
        /// 从存档恢复
        /// </summary>
        public void Restore() { }

        /// <summary>
        /// 强制设置
        /// </summary>
        public virtual void Preset(int tableId)
        {
            if (data == null)
            {
                switch (cellType)
                {
                    case CellType.Empty:
                        break;
                    case CellType.Piece:
                        data = new PieceCell(tableId);
                        break;
                    case CellType.Producer:
                        data = new ProducerCell(tableId);
                        break;
                    case CellType.ExtraItem:
                        data = new ExtraItemCell(tableId);
                        break;
                }
            }
            else
            {
                data.SetPiece(tableId);
            }
            SetData();
        }
        /// <summary>
        /// 强制设置
        /// </summary>
        public virtual void Preset(BaseCell cellData)
        {
            data = cellData;
            SetData();
        }

        /// <summary>
        /// 初始随机棋盘
        /// </summary>
        public void Random() { }

        /// <summary>
        /// 棋子等级发生变化
        /// </summary>
        public void LvChange(int tableId)
        {
            Preset(tableId);
            this.SendCommand(new UpadtePieceCommand(CalculatePos(Index), data.Piece));
        }

        protected virtual void SetData()
        {
            AssetUtil assetUtil = this.GetUtility<AssetUtil>();
            mainImage.sprite = assetUtil.GetPieceSprite(data.Piece);
        }

        Transform _cacheParent;
        bool isRayValid = true;
        protected virtual void OnBeginDragEvent(PointerEventData eventData)
        {
            if (eventData.button != PointerEventData.InputButton.Left) return;

            TypeEventSystem.Global.Send(new SelectPieceEvent() { pos = CalculatePos(Index) });
            isRayValid = false;
            _cacheParent = transform.parent;
            transform.SetParent(transform.root);
            UICheeseBoardGrid.Unselect();
            TypeEventSystem.Global.Send(new BeginDragEvent() { cell = this });
        }
        protected virtual void OnDragEvent(PointerEventData eventData)
        {
            if (eventData.button != PointerEventData.InputButton.Left) return;

            transform.position = eventData.position;
        }
        protected virtual void OnEndDragEvent(PointerEventData eventData)
        {
            if (eventData.button != PointerEventData.InputButton.Left) return;

            GameObject go = eventData.pointerCurrentRaycast.gameObject;
            if (go != null && go.TryGetComponent(out IPieceDrag pieceDrag))
            {
                if (pieceDrag.OnEndDrag(this, out int index))
                {
                    TypeEventSystem.Global.Send(new SelectPieceEvent() { pos = CalculatePos(index) });
                    UICheeseBoardPanel.SelectGrid(CalculatePos(index));
                }
                else
                {
                    SetPos(_cacheParent);
                    //UICheeseBoardPanel.SelectGrid(CalculatePos(_cacheParent.GetSiblingIndex()));
                    Debug.Log("棋子没有交互行为");
                }
            }
            else
            {
                SetPos(_cacheParent);
                //UICheeseBoardPanel.SelectGrid(CalculatePos(_cacheParent.GetSiblingIndex()));
                Debug.Log("棋子未拖动到棋盘上");
            }
            isRayValid = true;
            _cacheParent = null;
            EndDragTargetEffect();
        }
        bool ICanvasRaycastFilter.IsRaycastLocationValid(Vector2 sp, Camera eventCamera)
        {
            return isRayValid;
        }
        void OnPointerClickEvent(PointerEventData eventData)
        {
            if (eventData.button != PointerEventData.InputButton.Left) return;
            (int, int) pos = CalculatePos(Index);
            if (!UICheeseBoardPanel.CurSelect.Equals(pos))
            {
                TypeEventSystem.Global.Send(new SelectPieceEvent() { pos = pos });
                UICheeseBoardPanel.SelectGrid(pos);
            }
            else
            {
                OnSelect();
            }
        }

        public virtual bool OnEndDrag(Cell dragCell, out int index)
        {
            index = Index;
            //合成
            return Synthesis(dragCell);

            //return false;
        }

        /// <summary>
        /// 合成
        /// </summary>
        protected virtual bool Synthesis(Cell cell)
        {
            if (!IsTarget(cell))
            {
                return false;
            }
            //将棋子升级
            LvChange(data.Piece.PieceId + 1);
            cell.DestroyCell(false);
            return true;
        }
        /// <summary>
        /// 设置棋子位置
        /// </summary>
        /// <param name="parent"></param>
        public void SetPos(Transform parent)
        {
            transform.SetParent(parent);
            transform.localPosition = Vector3.zero;
            if (_cacheParent != parent)
            {
                int oldIndex = _cacheParent.GetSiblingIndex();
                int newIndex = parent.GetSiblingIndex();

                this.SendCommand(new ChangePiecePosCommand(CalculatePos(oldIndex), CalculatePos(newIndex)));
            }
            UICheeseBoardPanel.SelectGrid(CalculatePos(parent.GetSiblingIndex()));
        }
        /// <summary>
        /// 销毁棋子
        /// </summary>
        public void DestroyCell(bool unselect = true)
        {
            //Destroy(gameObject);
            TypeEventSystem.Global.Register<DestroyPieceEvent>(a =>
            {
                beDestroyed = true;
                Destroy(gameObject);
            }).UnRegisterWhenGameObjectDestroyed(gameObject);
            (int, int) pos;
            if (_cacheParent != null)
            {
                pos = CalculatePos(_cacheParent.GetSiblingIndex());
            }
            else
            {
                pos = CalculatePos(Index);
            }
            this.SendCommand(new DestroyPieceCommand(pos));

            if (unselect)
            {
                UICheeseBoardPanel.UnselectGrid();

            }
        }

        public virtual void OnSelect()
        {

        }
        public virtual bool CanSplitter(int maxLv)
        {
            if (Data.Piece.PieceLv > maxLv || Data.Piece.PieceLv == 1)
            {
                Debug.Log("棋子无法拆分");
                return false;
            }
            return true;
        }
        public virtual void OnSplitter()
        {
            int id = data.Piece.PieceId - 1;
            //当前棋子降一级
            LvChange(id);
            //生成一个新的棋子
            this.SendCommand(new PutInPieceInPosCommand(id, CalculatePos(Index)));
        }

        public virtual bool CanUpgrade()
        {
            return data.Piece.PieceLv < data.Piece.PieceMaxLv;
        }
        public virtual void Upgrade()
        {
            LvChange(data.Piece.PieceId + 1);
        }

        public virtual void EndDragTargetEffect()
        {
            TypeEventSystem.Global.Send<EndDragEvent>();
        }

        protected virtual bool IsTarget(Cell cell)
        {
            return cell.IsDragTarget(this);
        }

        protected virtual bool IsDragTarget(Cell dragCell)
        {
            return (data.Piece.PieceId == dragCell.Data.Piece.PieceId &&
               data.Piece.PieceLv < data.Piece.PieceMaxLv);
        }

        void OnBeginDragEvent(BeginDragEvent arg)
        {
            mainImage.color = arg.cell.IsTarget(this) ? Color.white : new Color(1, 1, 1, 0.5f);
        }
        void OnEndDragEvent(EndDragEvent arg)
        {
            mainImage.color = Color.white;
        }
    }
}
